using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 1、启动游戏先去账号服请求服务器列表  getserverlist
// 2、如果本地没有存账号显示登录弹窗面板账号注册或登录 userlogin
// 3、点击开始按钮，创建Socket，连接成功后
// 4、获取玩家信息 getuserinfo
// 5、发送socket消息，protobuf，LoginRequset


public class LoginControl : ControlBase
{
    /// <summary>
    /// 存储玩家 OpenID 的键名。
    /// </summary>
    private string openIdkey = "openIdkey";
    /// <summary>
    /// 玩家 OpenID 的默认值。
    /// </summary>
    private string defaultOpenIdkey = "DEF";
    /// <summary>
    /// 存储玩家 OpenID 密码的键名。
    /// </summary>
    private string openIdPw = "openIdPw";
    /// <summary>
    /// 玩家 OpenID 密码的默认值。
    /// </summary>
    private string defaultOpenIdPw = "DEF";

    /// <summary>
    /// 存储最后选择服务器索引的键名。
    /// </summary>
    private string lastServerIndex = "lastServerIndex";

    /// <summary>
    /// 存储所有服务器列表的 JSON 对象列表。
    /// </summary>
    private List<JObject> serverList;
    /// <summary>
    /// 存储玩家专属服务器列表的 JSON 对象列表。
    /// </summary>
    private List<JObject> myServerList;

    /// <summary>
    /// 存储玩家最后登录服务器信息的 JSON 对象。
    /// </summary>
    private JObject lastServer;
    /// <summary>
    /// 存储推荐服务器信息的 JSON 对象。
    /// </summary>
    private JObject recommend;

    /// <summary>
    /// 表示是否已连接服务器的标志。
    /// </summary>
    public bool connect;
    /// <summary>
    /// 表示是否已发送用户信息请求的标志。
    /// </summary>
    public bool send;

    private void OnConnect(SocketClient client)
    {
        Debug.Log("---------OnConnect");
       
        // 标记已连接服务器
        connect = true;
        Debug.Log(connect);
        // GameEvent.Instance.DispatchEvent("101");
        MainThreadDispatcher.Instance.Enqueue(RequestUserInfo);
    }

    private void OnSocketConnect(object[] args)
    {
        RequestUserInfo();
    }

    /// <summary>
    /// 请求用户信息，构建请求 URL 并发送 HTTP GET 请求。
    /// </summary>
    private void RequestUserInfo()
    {
        // 标记已发送用户信息请求
        send = true;
        Debug.Log(send);
        // 构建请求用户信息的 URL
        string url = $"{AppConst.LoginRoot_Url}tk/getUserInfo?openId={LoginManager.Instance.openId}" +
                     $"&serverId={LoginManager.Instance.ServerId}" +
                     $"&token={LoginManager.Instance.token}" +
                     $"&platform=4" +
                     $"&sub_channel={AppConst.LoginRoot_SubChannel}" +
                     $"&version={AppConst.LoginRoot_PackageVersion}";
        // 调用网络管理器发送 HTTP GET 请求，并指定回调方法
        NetworkManager.Instance.SendGetHttp(url, OnReceiveLogin, null);
        Debug.LogWarning("http:" + url);
    }

    /// <summary>
    /// 每帧更新时检查连接和请求标志，满足条件时请求用户信息。
    /// </summary>
    private void Update()
    {
        // 如果已发送请求或未连接服务器，则跳过后续逻辑
        if (send ||!connect) return;
        if(connect) 
        {
            // 若已连接服务器，则请求用户信息
            RequestUserInfo();
        }
    }

    /// <summary>
    /// 处理用户信息请求的响应，解析响应数据并进行登录操作。
    /// </summary>
    /// <param name="str">服务器返回的响应字符串。</param>
    private void OnReceiveLogin(string str)
    {
        if (string.IsNullOrWhiteSpace(str))
        {
            Debug.LogError("OnReceiveLogin: 接收的JSON字符串为空");
            return;
        }
        try
        {
            // 3. 使用try-catch捕获解析异常
            JObject json = JObject.Parse(str);

            // 后续正常处理逻辑...
        }
        catch (JsonReaderException ex)
        {
            // 输出错误信息和原始字符串，便于调试
            Debug.LogError($"OnReceiveLogin: JSON解析失败 - {ex.Message}, 原始字符串: {str}");
        }
        catch (Exception ex)
        {
            Debug.LogError($"OnReceiveLogin: 处理失败 - {ex.Message}");
        }
        Debug.Log(str);
        // 检查响应字符串是否有效
        if (str != null && !str.Equals(""))
        {
            // 解析响应字符串为 JSON 对象
            JObject data = JObject.Parse(str);
            // 更新全局常量中的用户 ID
            AppConst.UserId = (int)data["uid"];
            // 更新全局常量中的令牌
            AppConst.Token = (int)data["token"];
            // 从玩家偏好设置中获取 OpenID
            string openId = PlayerPrefs.GetString(openIdkey);
            // 调用网络管理器的登录请求方法
            NetManager.LoginRequest(openId, (data) =>
            {
                // 登录成功后的处理
                if (!LoginManager.Instance.isLogin)
                {
                    // 标记用户已登录
                    LoginManager.Instance.isLogin = true;
                    // 执行加载操作
                    ExcuteLoading();
                }
            });
        }
    }

    /// <summary>
    /// 执行加载操作，关闭登录面板并打开主面板。
    /// </summary>
    private void ExcuteLoading()
    {
        // 调用 UI 管理器关闭登录面板
        // UIManager.Instance.Close<LoginPanel>();
        // 调用 UI 管理器打开主面板
        UIManager.Instance.OpenWindow("MainPanel");
    }

    /// <summary>
    /// 处理服务器列表请求的响应，解析响应数据并根据用户信息进行相应操作。
    /// </summary>
    /// <param name="str">服务器返回的响应字符串。</param>
    // 服务器列表返回
    private void OnReceiveServerList(string str)
    {
        Debug.Log(str);

        // 检查响应字符串是否有效
        if (str != null && !str.Equals(""))
        {
            // 解析响应字符串为 JSON 对象
            JObject data = JObject.Parse(str);
            // 设置服务器列表
            SetServerList(data);

            // 从玩家偏好设置中获取用户 ID 和密码
            string user = PlayerPrefs.GetString(openIdkey, defaultOpenIdkey);
            string userPw = PlayerPrefs.GetString(openIdPw, defaultOpenIdPw);
            // 如果是默认用户
            if (user == defaultOpenIdkey && userPw == defaultOpenIdPw)
            {
                // 打开登录弹窗面板
                // UIManager.Instance.Open<LoginPopupPanel>();
            }
            else
            {
                // 调用登录管理器请求用户信息
                LoginManager.Instance.RequestUser(user, userPw, (code) =>
                {
                    if (code != 0)
                    {
                        // 若请求失败，打开登录弹窗面板
                        // UIManager.Instance.Open<LoginPopupPanel>();
                    }
                });
            }
        }
        
    }

    /// <summary>
    /// 处理服务器列表数据，缓存登录数据并设置登录管理器的服务器信息。
    /// </summary>
    /// <param name="data">包含服务器列表信息的 JSON 对象。</param>
    // 服务器列表处理
    private void SetServerList(JObject data)
    {
        // 缓存登录数据
        CacheLoginData(data);

        // 从玩家偏好设置中获取最后选择的服务器索引，若不存在则使用默认值 0
        int lastIndex = PlayerPrefs.GetInt(lastServerIndex, 0);

        // 有最近登录显示最近登录，没有显示推荐，否则显示第一个服
        if (lastServer != null) 
        {
            for (int i = 0; i < serverList.Count; i++)
            {
                if (serverList[i]["server_id"].ToString() == lastServer["serverid"].ToString())
                {
                    lastIndex = i;
                }
            }
        }

        // 存储数据
        // PlayerManager.serverInfo = this.serverList[lastIndex];
        // 获取要连接的服务器信息
        JObject server = serverList[lastIndex];
        // 设置登录管理器的 Socket 地址
        LoginManager.Instance.SocketAddress = (string)server["ip"];
        // 设置登录管理器的 Socket 端口
        LoginManager.Instance.SocketPort = (int)server["port"];
        // 设置登录管理器的服务器 ID
        LoginManager.Instance.ServerId = (int)server["server_id"];
        // 设置登录管理器的服务器状态
        LoginManager.Instance.state = (int)server["state"];
            
        // 界面赋值
        // this.serverImage.sprite = Util.LoadSprite(ServerStateIconDef[LoginManager.state])
        // this.serverMes.text = PlayerManager.serverInfo.name
    }

    /// <summary>
    /// 缓存登录数据，包括服务器列表、玩家专属服务器列表和最后登录服务器信息，并对服务器列表进行排序。
    /// </summary>
    /// <param name="data">包含登录数据的 JSON 对象。</param>
    private void CacheLoginData(JObject data)
    {
        
        // 初始化服务器列表
        serverList = new List<JObject>();
        // 初始化玩家专属服务器列表
        myServerList = new List<JObject>();
        // 遍历服务器列表并添加到 serverList 中
        foreach (JObject server in data["serverList"])
        {
            serverList.Add(server);
        }
        // 对服务器列表进行排序
        serverList.Sort((a, b) =>
        {
            if (a["isnew"] == b["isnew"])
            {
                // 若新服状态相同，按服务器 ID 降序排序
                return (int)b["server_id"] - (int)a["server_id"];
            }
            else
            {
                // 若新服状态不同，新服排在前面
                return (int)a["isnew"] - (int)b["isnew"];
            }
        });
            
        // 遍历玩家专属服务器列表并添加到 myServerList 中
        foreach (JObject server in data["myServerList"])
        {
            myServerList.Add(server);
        }

        // 获取最后登录服务器信息
        lastServer = (JObject)data["lastServer"];
        // 注释掉的代码：获取推荐服务器信息
        // recommend = (JObject)data["recommend"];
    }

    /// <summary>
    /// 请求服务器列表，构建请求 URL 并发送 HTTP GET 请求。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="onReceiveServerList">服务器列表请求的回调方法。</param>
    private void RequestServerList(string userId, Action<string> onReceiveServerList)
    {
        // 构建请求服务器列表的 URL
        string url = $"{AppConst.LoginRoot_Url}tk/getServerList?openId={userId}&channel={AppConst.LoginRoot_Channel}&plat=android&sub_channel={AppConst.LoginRoot_SubChannel}&server_version={AppConst.LoginRoot_Version}";
        // 调用网络管理器发送 HTTP GET 请求，并指定回调方法
        NetworkManager.Instance.SendGetHttp(url, onReceiveServerList, null);
        
    }

    /// <summary>
    /// 请求 Socket 登录，创建 Socket 客户端实例并尝试连接。
    /// </summary>
    private void RequestSoketLogin()
    {
        // 注释掉的代码：断开当前 Socket 连接
        // SocketClient.Instance.Disconnect();
        // 注释掉的代码：设置 Socket 地址和端口
        // SocketClient.Instance.SetIpAddress(LoginManager.Instance.SocketAddress, LoginManager.Instance.SocketPort);
        // 注释掉的代码：尝试连接 Socket
        // SocketClient.Instance.TryConnect();

        // 创建一个新的 Socket 客户端实例并添加到网络管理器中
        SocketClient socketClient = NetworkManager.Instance.AddSocket(SocketType.LOGIN, LoginManager.Instance.SocketAddress, LoginManager.Instance.SocketPort);
        socketClient.OnConnects += OnConnect;
        // 尝试连接 Socket
        socketClient.TryConnect();
    }
    public void StartGame()
    {
        // 请求 Socket 登录
        RequestSoketLogin();
    }
    public override void Init(UIWindow uiBase)
    {
        Debug.Log("GameControl Init");
        // 从玩家偏好设置中获取用户 ID，若不存在则使用默认值
        string userId = PlayerPrefs.GetString(openIdkey, defaultOpenIdkey);
        // 请求服务器列表，并指定回调方法
        RequestServerList(userId, OnReceiveServerList);
        // 订阅 "101" 事件，当该事件触发时调用 OnConnect 方法
        GameEvent.Instance.AddEvent("101", OnSocketConnect);
    }

    public override void OnEnable()
    {
        Debug.Log("GameControl OnEnable");
    }

    public override void OnDestory()
    {
        Debug.Log("GameControl OnDestory");
    }
}
